package parser;

import antlr.RecognitionException;
import java.util.*;
import java.io.*;

public class BytecodeFile {
    
    BytecodeFile(String filename, ConstantTable constants, List<Function> functions, List<ClassDefn> classes, Stmt script) {                
        this.constants = constants;
        this.functions = functions;
        this.classes =   classes;
        this.script =    script.returns();
        this.file = constants.constant(filename);
    }
        
    ConstantTable constants;
    List<Function> functions;
    List<ClassDefn> classes;
    Stmt script;
    int file;
    
    void dump(PrintStream out) throws RecognitionException {
        Disassembler d = new Disassembler();
        out.println("Version: " + Version.NUMBER);
        out.println("(" + 256 + " standard names)");
        NameTable.dump(out);
        constants.dump(out);
        out.println("Functions: " + functions.size());
        for (Function f: functions) 
            f.dump(out, d);
        out.println("Classes " + classes.size());
        for (ClassDefn c: classes)
            c.dump(out);
            out.println("Script:");
        d.dumpCode(script, out);
    }
    
    public byte[] getBytes() throws RecognitionException {
        ByteStream stream = new ByteStream();
        write(stream);
        return stream.toByteArray();
    }
    
    static final int MAGIC_NUMBER = 20601;
    
    void write(ByteStream out) throws RecognitionException {
        out.writeShort(MAGIC_NUMBER);
        out.writeShort(Version.NUMBER);
        NameTable.write(out);
        constants.write(out);
        out.writeShort(file);
        out.writeShort(functions.size());
        for (Function f: functions) 
            f.write(out);
        out.writeShort(classes.size());
        for (ClassDefn c: classes)
            c.write(out);
        int patch = out.here();
        out.writeShort(0); 
        out.clearLineNumbers();
        script.write(out);
        int offset = out.here()-patch-2;
        if ((offset & 1) != 0)
            out.write(0);
        out.patchShort(patch, offset);
    }
    
}
